package mx.spring.mvc.core;

import java.io.File;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import javax.servlet.ServletContext;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;

import mx.spring.mvc.annotation.MXController;
import mx.spring.mvc.annotation.MXRequestUrl;

import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;

public class FrameworkListener implements ServletContextListener {

	@Override
	public void contextDestroyed(ServletContextEvent e) {
	}

	@Override
	public void contextInitialized(ServletContextEvent e) {
		Map<String,String> configInfo=new HashMap<String, String>();
		ServletContext sct=e.getServletContext();
		String xmlPath=sct.getRealPath("")+sct.getInitParameter("mx_spring");
		try {
			configInfo.putAll(parseXML(xmlPath));
			configInfo.putAll(parseAnnotation(xmlPath));
			sct.setAttribute("mx_spring", configInfo);
		} catch (Exception exception) {
			exception.printStackTrace();
		}
	}
	
	@SuppressWarnings({ "unchecked", "rawtypes" })
	private Map<String,String> parseAnnotation(String xmlPath) throws Exception{
		SAXReader reader=new SAXReader();
		Map<String,String> map=new HashMap<String, String>();
		Document doc=reader.read(xmlPath);
		Element rootNode=doc.getRootElement();
		Element scanNode=rootNode.element("mxScan");
		if(scanNode==null)return null;
		//获得包名
		String[] packageNames=scanNode.attributeValue("package").split(",");
		//获得包中的所有类
		List<Class> list=new ArrayList<Class>();
		String classpath=Thread.currentThread().getContextClassLoader().getResource("").getPath();
		for(String packageName:packageNames){
			File[] files=new File(classpath+packageName.replace(".", "/")).listFiles();
			for(File f:files){
				if(!f.isDirectory()){
					String fname=f.getName().substring(0,f.getName().lastIndexOf("."));
					list.add(Class.forName(packageName+"."+fname));
				}
			}
		}
		//解析类中的Annotation信息
		for(Class cls:list){
			if(cls.isAnnotationPresent(MXController.class)){
				String controllerUrl="";
				String methodUrl="";
				if(cls.isAnnotationPresent(MXRequestUrl.class)){
					MXRequestUrl ctrUrl=(MXRequestUrl)cls.getAnnotation(MXRequestUrl.class);
					controllerUrl=ctrUrl.value();
				}
				Method[] methods=cls.getMethods();
				for(Method method:methods){
					if(method.isAnnotationPresent(MXRequestUrl.class)){
						MXRequestUrl mUrl=(MXRequestUrl)method.getAnnotation(MXRequestUrl.class);
						methodUrl=mUrl.value();
						String param="";
						for(Class para : method.getParameterTypes()){
							param=para.getName();
						}
						map.put(controllerUrl+methodUrl, cls.getName()+","+method.getName()+","+param);
					}
				}
			}
		}
		
		return map;
	}
	
	/*
	 * 用于解析XML文件中的数据
	 */
	@SuppressWarnings("unchecked")
	private Map<String,String> parseXML(String xmlPath) throws Exception{
		SAXReader reader=new SAXReader();
		Map<String,String> map=new HashMap<String, String>();
		Document doc=reader.read(xmlPath);
		Element rootNode=doc.getRootElement();
		Iterator<Element> controllerIt=rootNode.elementIterator();
		while(controllerIt.hasNext()){
			Element controllerNode=controllerIt.next();
			if(controllerNode.getName().equals("mxController")){
				String classurl=controllerNode.attributeValue("url");
				String classname=controllerNode.attributeValue("class");
				Iterator<Element> it=controllerNode.elementIterator();
				while(it.hasNext()){
					Element methodNode=it.next();
					if(methodNode.getName().equals("mxMethod")){
						String methodurl=methodNode.attributeValue("url");
						String methodname=methodNode.attributeValue("name");
						String methodparam=methodNode.attributeValue("param");
						map.put(classurl+methodurl, classname+","+methodname+","+methodparam);
					}
				}
			}
		}
		return map;
	}

}
